﻿using CoreWebApiNuGet.JwtAuthentication;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using static System.Collections.Specialized.BitVector32;

namespace CoreWebApiNuGet.ProgramExtend
{
    /// <summary>
    /// 添加Jwt配置
    /// </summary>
    public static class AddJwtProgram
    {
        /// <summary>
        /// 添加Jwt鉴权
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        public static IServiceCollection AddJwtAuth(this IServiceCollection services, IConfiguration configuration, Action<JwtValidationOptions> configureAction = null)
        {
            // 初始化票据
            var options = new JwtIssueOptions();

            options.Issuer = configuration["JwtIssue:Issuer"] ?? "Issuer";
            options.Audience = configuration["JwtIssue:Audience"] ?? "Audience";
            options.Expires = DateTime.UtcNow.AddMinutes(int.Parse(configuration["JwtIssue:Expires"] ?? "0"));
            options.Secret = JwtUtility.GetRandomString(256, true, true, true, false, string.Empty);
            options.DefaultSecurityType = SecurityAlgorithms.HmacSha256;

            //单例注入票据
            services.AddSingleton(options);

            // 单例注入服务
            services.AddSingleton<IJwtTokenAuthorityService, JwtTokenAuthorityService>();

            // 添加身份验证服务
            var jwtOptions = configuration.GetSection("JwtValidation").Get<JwtValidationOptions>();
            configureAction?.Invoke(jwtOptions);
            AddJwtAuthentication(services, jwtOptions);

            return services;
        }

        /// <summary>
        /// 添加JWT认证
        /// </summary>
        /// <param name="services"></param>
        /// <param name="jwtOptions">jwt验证选项</param>
        public static AuthenticationBuilder AddJwtAuthentication(this IServiceCollection services, JwtValidationOptions jwtOptions)
        {
            if (jwtOptions == null) throw new ArgumentNullException(nameof(jwtOptions));

            //services.AddAuthentication(options =>
            //{
            //    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            //    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            //    //options.DefaultForbidScheme
            //})

            return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    //options.Authority = "http://localhost:4123/";
                    options.Authority = jwtOptions.Authority;

                    //TokenValidationParameters parameters = new TokenValidationParameters
                    //{
                    //    ValidIssuer = jwtOptions.ValidIssuer,//验证发行者
                    //    ValidateIssuerSigningKey = jwtOptions.ValidateIssuerSigningKey,
                    //    IssuerSigningKey = jwtOptions.IssuerSigningKey,
                    //    //ValidateLifetime = true,//默认验证有效期 
                    //    //ClockSkew = TimeSpan.Zero,
                    //};

                    //if (!string.IsNullOrEmpty(jwtOptions.ValidAudience))
                    //    parameters.ValidAudience = jwtOptions.ValidAudience; //验证受众

                    ////接收到token时，验证配置
                    //options.TokenValidationParameters = parameters;

                    options.RequireHttpsMetadata = false;
                    options.Events = jwtOptions.JwtBearerEvents;

                    options.TokenValidationParameters.ClockSkew = TimeSpan.FromSeconds(60);
                    options.TokenValidationParameters.ValidateAudience = jwtOptions.ValidateAudience;

                    options.TokenValidationParameters.ValidIssuers = jwtOptions.ValidIssuers;
                    options.TokenValidationParameters.IssuerValidator = (string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
                    {
                        if (validationParameters.ValidateIssuer)
                        {
                            if (!string.IsNullOrEmpty(validationParameters.ValidIssuer) && validationParameters.ValidIssuer != issuer)
                                throw new SecurityTokenInvalidIssuerException($"Issuer validation failed.The security token issuer: '{issuer}' Did not match valid issuers: '{validationParameters.ValidIssuer}'");

                            if (validationParameters.ValidIssuers.Any() && !validationParameters.ValidIssuers.Contains(issuer))
                                throw new SecurityTokenInvalidIssuerException($"Issuer validation failed.The security token issuer: '{issuer}' Did not match valid issuers: '{string.Join("','", validationParameters.ValidIssuers.Distinct())}'");
                        }
                        return issuer;
                    };
                });
        }

    }
}
